package sample.algo.sistr.algosample.algos.arrays;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import java.security.InvalidParameterException;
import java.util.Arrays;

import sample.algo.sistr.algosample.R;
import sample.algo.sistr.algosample.algos.Algo;

public class Algo01  extends Algo {

    private TextView textViewTestResult;
    private EditText editText;
    /*
    Give all possible subsets of a set or powerset.
    For example : If a set of 3 elements. {1,2,3} is given, then all possible subsets would be
    {} - Empty Set
    {1,2,3} - Full set itself
    {1}
    {2}
    {3}
    {1,2}
    {2,3}
    {1,3}
    */

    public Algo01(Context context) {
        super("Powerset", context);
        textViewTestResult = null;
        editText = null;
    }

    @Override
    public View GetDisplay() {
        ViewGroup root = (ViewGroup) ((LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.algo_array_01, null);

        textViewTestResult = (TextView)root.findViewById(R.id.textViewTest);

        Button buttonTest = (Button)root.findViewById(R.id.buttonTest);
        buttonTest.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                StringBuilder testResult = new StringBuilder();

                // test on well formed input
                int i = 0;
                testResult.append("PowerSet: \n");
                int [][] powerSet = function(new int[]{0, 1, 2});
                for(int[] s : powerSet) {
                    testResult.append(Arrays.toString(s)).append(", ");
                }

                // test on invalid input


                if(textViewTestResult != null)
                    textViewTestResult.setText(testResult);
            }
        });

        editText = (EditText) root.findViewById(R.id.editText);
        editText.setText("[1, 3, 5]");

        Button buttonRun = (Button)root.findViewById(R.id.buttonRun);
        buttonRun.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                StringBuilder testResult = new StringBuilder();

                String stringInput = editText.getText().toString();
                stringInput = stringInput.replaceAll("\\s+","");

                String[] intsStr = stringInput.replaceAll("\\[", "").replaceAll("\\]", "").split(",");

                int[] ints = new int[intsStr.length];

                for (int i = 0; i < intsStr.length; i++) {
                    try {
                        ints[i] = Integer.parseInt(intsStr[i]);
                    } catch (NumberFormatException nfe) {  };
                }

                int [][] powerSet = function(ints);
                for(int[] s : powerSet) {
                    testResult.append(Arrays.toString(s)).append(", ");
                }


                if(textViewTestResult != null)
                    textViewTestResult.setText(testResult);
            }
        });

        return root;
    }

    // Overall recursive idea. The power set of a set of size n, is the power set of the set of size n-1 (with one random element removed), plus the union of that subset power set union the removed element.
    // Example: {1, 2, 3}, we get a subset by removing 3 -> {1, 2}
    // PowerSet({1, 2, 3}) = PowerSet({1, 2}) + 3*PowerSet({1, 2});
    private int [][] function(int set[]) {
        if(set == null)
            throw new InvalidParameterException("input can't be null !");

        if(set.length == 0) {
            int result [][] = new int[1][];
            result[0] = set;
            return result;
        }

        // get a subset
        int subset[] = new int[set.length-1];
        System.arraycopy(set, 0, subset, 0, set.length-1);

        // Get the popped element for readability
        int popped = set[set.length-1];

        // Get the power set of the subset
        int [][] subsetPowerSet = function(subset);

        // Allocate the result of our function, the number of set in the power set is twice the number of set in the power set of the subset
        int result[][] = new int [subsetPowerSet.length*2][];

        // We fill the first half of result with the power set of the subset
        System.arraycopy(subsetPowerSet, 0, result, 0, subsetPowerSet.length);

        // Add in the result the union of the popped element with the subset power set.
        int i = 0;
        for(int s[] : subsetPowerSet) {
            int newSet[] = new int[s.length+1];
            System.arraycopy(s, 0, newSet, 0, s.length);
            newSet[s.length] = popped;
            result[subsetPowerSet.length + i++] = newSet;
        }

        return result;
    }


}
